﻿namespace PlayListBundler
{
    using System.Collections.Generic;
    using System;

    /// <summary>
    /// Full file: Represents all string informations of a file.
    /// </summary>
    public struct FFile
    {
        /// <summary>The file path.</summary>
        public string Path;
        /// <summary>The original name.</summary>
        public string OrigName;
        /// <summary>The new (modified) name.</summary>
        public string NewName;

        /// <summary>
        /// Initializes a new instance of the <see cref="FFile"/> struct.
        /// </summary>
        /// <param name="path">The file path.</param>
        /// <param name="origName">The original name.</param>
        /// <param name="newName">The new (modified) name.</param>
        public FFile(string path, string origName, string newName)
        {
            Path = path;
            OrigName = origName;
            NewName = newName;
        }
    }

    /// <summary>An extended dictionary. 
    /// Keys and values are stored in separated lists.</summary>
    public class Files
    {
        /// <summary>All files as a path.</summary>
        public List<string> Path;
        /// <summary>All files with their original name.</summary>
        public List<string> OrigName;
        /// <summary>All files with their new (modified) name.</summary>
        public List<string> NewName;
        /// <summary>The number of the elements in the dictionary.</summary>
        public int Count{ get { return Path.Count; } }

        /// <summary>Initializes a new instance of the <see cref="Files"/> class.</summary>
        public Files()
        {
            Path = new List<string>();
            OrigName = new List<string>();
            NewName = new List<string>();
        }

        /// <summary>Initializes a new instance of the <see cref="Files"/> class.</summary>
        /// <param name="capacity">The maximum number of files.</param>
        public Files(int capacity)
        {
            Path = new List<string>(capacity);
            OrigName = new List<string>(capacity);
            NewName = new List<string>(capacity);
        }

        /// <summary>
        /// Adds the passed file with its path and new name into the list.
        /// </summary>
        /// <param name="path">The file path.</param>
        public void Add(string path)
        {
            Path.Add(path);
            OrigName.Add(Pattern.GetFileName(path));
            NewName.Add(Pattern.GetFileName(path));
        }

        /// <summary>
        /// Adds the passed file with its path and new name into the list.
        /// </summary>
        /// <param name="path">The file path.</param>
        /// <param name="newName">The new (modified) name.</param>
        public void Add(string path, string newName)
        {
            Path.Add(path);
            OrigName.Add(Pattern.GetFileName(path));
            NewName.Add(newName);
        }

        /// <summary>
        /// Inserts at the passed index position a new file 
        /// with its path and new name into the list.
        /// </summary>
        /// <param name="index">The index position.</param>
        /// <param name="path">The file path.</param>
        /// <param name="newName">The new (modified) name.</param>
        public void Insert(int index, string path, string newName)
        {
            Path.Insert(index, path);
            OrigName.Insert(index, Pattern.GetFileName(path));
            NewName.Insert(index, newName);
        }

        /// <summary>
        /// Gets the full file of the passed original filename.
        /// </summary>
        /// <param name="origName">The original filename.</param>
        /// <returns>The full file.</returns>
        public FFile GetFFileFromOrigName(string origName)
        {
            int index = -1;
            FFile ffile; 
            try
            {
                index = OrigName.IndexOf(origName);
                ffile = new FFile(Path[index], OrigName[index], NewName[index]);
            } 
            catch (ArgumentOutOfRangeException)
            {
                throw new KeyNotFoundException("This file does not exist.");
            }
            return ffile;
        }

        /// <summary>
        /// Gets the full file of the passed new filename.
        /// </summary>
        /// <param name="newName">The new (modified) name.</param>
        /// <returns>The full file.</returns>
        public FFile GetFFileFromNewName(string newName)
        {
            int index = -1;
            FFile ffile;
            try
            {
                index = NewName.IndexOf(newName);
                ffile = new FFile(Path[index], OrigName[index], NewName[index]);
            }
            catch (ArgumentOutOfRangeException)
            {
                throw new KeyNotFoundException("This file does not exist.");
            }
            return ffile;
        }

        /// <summary>
        /// Changes the new filename of the passed <paramref name="path"/> with the 
        /// passed <paramref name="newName"/>.
        /// </summary>
        /// <param name="index">The index in the filelist.</param>
        /// <param name="newName">The new (modified) name.</param>
        public void ChangeNewName(int index, string newName)
        {
            NewName.Insert(index, newName);
            NewName.RemoveAt(index + 1);
        }

        /// <summary>
        /// Changes the new filename of the passed <paramref name="path"/> with the 
        /// passed <paramref name="newName"/>.
        /// </summary>
        /// <param name="path">The file path.</param>
        /// <param name="newName">The new (modified) name.</param>
        public void ChangeNewName(string path, string newName)
        {
            int index = Path.IndexOf(path);
            NewName.Insert(index, newName);
            NewName.RemoveAt(index + 1);
        }

        /// <summary>
        /// Removes the passed file.
        /// </summary>
        /// <param name="path">The file path.</param>
        public void Remove(string path)
        {
            int index = Path.IndexOf(path);
            Path.Remove(path);
            OrigName.RemoveAt(index);
            NewName.RemoveAt(index);
        }

        /// <summary>Removes the file of the passed index position.</summary>
        /// <param name="index">The index value in the list of the file to remove.</param>
        public void RemoveAt(int index)
        {
            Path.RemoveAt(index);
            OrigName.RemoveAt(index);
            NewName.RemoveAt(index);
        }

        /// <summary>Removes all elements from the dictionary.</summary>
        public void Clear()
        {
            Path.Clear();
            OrigName.Clear();
            NewName.Clear();
        }

        /// <summary>Clears and nulls the key and value lists.</summary>
        public void Dispose()
        {
            Clear();
            Path = null;
            OrigName = null;
            NewName = null;
        }
    }
}
